Mobilisation and movements
| Date | Presenters | Method |
|---|---|---|
| 5 June: | Rasmus B., Andre D., Josefine E., Ioanna L., Santiago C. | surveys |
| 12 June: | Omar B., Lela E., Niclas W. | network analysis |
| 19 June: | NO CLASS MEETING | |
| 26 June: | Colombe I., Konstantin S., Jakob W., Veronika L. | ethnography |
| 26 June: | Maksim K., Felix S., Jon L.D., Damir S., Korbinian M. | case study |
| Date | Presenters | Method |
|---|---|---|
| 3 July: | Alexander V., Luis G., Oscar O., Mia C. | descriptive inference |
| 10 July: | Lina S., Stephen W., Philomena B., Aarón Z. | ethnography |
| 17 July: | Corinna Z., Eva M., and Rostislav N. | TBD |
| 24 July: | Sebastian K., Thomas R., Emilia Z., Florian P. | TBD |
| 24 July: | Lorenz F., Daniel B., Medina H. | quant. text analysis |
| Date | Presenters | Method |
|---|---|---|
| 15 May: | Idil M., Zeynep P., Liesl W., Selin K., Chiara W. | logistic regression |
| 22 May: | Gabriel W., Lina M., Florian S., Julian B. | discourse analysis |
| 29 May: | NO CLASS MEETING |
cultural
political
cultural
organisational
political
cultural
individual
organisational
political
cultural
individual
individual
organisational
political
cultural
organisational
individual
organisational
political
cultural
individual
organisational
political
cultural
cultural
individual
organisational
political
cultural
What are some goals of contemporary far-right movements that are not particular to institutional politics?
for many extra-institutional goals it is far-right movements (more than other actors) that have a major impact
international treaties - usually the realm of elite politics
more …
not unique: Global Compact for Migration (Rone and Fielitz 2023)
Take the survey at https://forms.gle/LNPvbC4h9QbycWYL7
which year do you guess was far-right social mobilisation most frequent?
most prominent far-right protest issue?
most common far-right mobilisation form?
what to do when non-violent far-right demonstrations are met with disruptive, possibly violent counter-mobilisation?
import { liveGoogleSheet } from "@jimjamslam/live-google-sheet";
import { aq, op } from "@uwdata/arquero";
// UPDATE THE LINK FOR A NEW POLL
surveyResults = liveGoogleSheet(
"https://docs.google.com/spreadsheets/d/e/" +
"2PACX-1vRUirGBSRIasLbdAX8eUL3CnbZMeyDlaJg641JdD1rmABt9Sn2cCyLdZDVc0vlllR18UEfSJiDBL3Bs/" +
"pub?gid=1046226459&single=true&output=csv",
10000, 1, 6); // adjust the last number to select all relevant columns
respondentCount = surveyResults.length;Most active year
active_yearCounts = aq.from(surveyResults)
.select("active_year")
.groupby("active_year")
.count()
.derive({ measure: d => "" })
// Calculate the maximum count from your dataset
active_year_maxCountRE = Math.max(...active_yearCounts.objects().map(d => d.count));
plot_active_year = Plot.plot({
marks: [
Plot.barY(active_yearCounts, {
x: "active_year",
y: "count",
fill: "active_year",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"2009",
"2010",
"2011",
"2012",
"2013",
"2014",
"2015",
"2016",
"2017",
"2018",
"2019"
],
range: [
"darkred",
"darkorange",
"goldenrod",
"forestgreen",
"blue",
"indigo",
"violet",
"brown",
"black",
"grey",
"white"
]
},
marginBottom: 80,
x: { label: "", tickSize: 2, tickRotate: -90, padding: 0.2,
domain: ["2009", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(active_yearCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, active_year_maxCountRE]
},
facet: { data: active_yearCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1600,
height: 500,
fontSize: 30,
},
});Most prominent issue
issueCounts = aq.from(surveyResults)
.select("issue")
.groupby("issue")
.count()
.derive({ measure: d => "" })
// Calculate the maximum count from your dataset
issue_maxCountRE = Math.max(...issueCounts.objects().map(d => d.count));
plot_issue = Plot.plot({
marks: [
Plot.barY(issueCounts, {
x: "issue",
y: "count",
fill: "issue",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"corruption",
"culture",
"economy",
"EU",
"foreign policy",
"gender",
"immigration",
"Islam",
"security",
"welfare"
],
range: [
"darkred",
"darkorange",
"goldenrod",
"forestgreen",
"blue",
"indigo",
"violet",
"brown",
"black",
"grey"
]
},
marginBottom: 100,
x: { label: "", tickSize: 2, tickRotate: -45, padding: 0.3,
domain: ["corruption", "culture", "economy", "EU", "foreign policy", "gender", "immigration", "Islam", "security", "welfare"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(issueCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, issue_maxCountRE]
},
facet: { data: issueCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1600,
height: 500,
fontSize: 30,
},
});Most common tactic/form
tacticCounts = aq.from(surveyResults)
.select("tactic")
.groupby("tactic")
.count()
.derive({ measure: d => "" })
// Calculate the maximum count from your dataset
tactic_maxCountRE = Math.max(...tacticCounts.objects().map(d => d.count));
plot_tactic = Plot.plot({
marks: [
Plot.barY(tacticCounts, {
x: "tactic",
y: "count",
fill: "tactic",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"boycott",
"confrontation",
"demonstration",
"occupation",
"symbolic",
"violence"
],
range: [
"darkred",
"darkorange",
"goldenrod",
"forestgreen",
"blue",
"indigo"
]
},
marginBottom: 100,
x: { label: "", tickSize: 2, tickRotate: -25, padding: 0.3,
domain: ["boycott", "confrontation", "demonstration", "occupation", "symbolic", "violence"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(tacticCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, tactic_maxCountRE]
},
facet: { data: tacticCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1600,
height: 500,
fontSize: 30,
},
});Italy
UK
Germany
Italy = [
{Year: 2008, Num: 42}, {Year: 2009, Num: 117}, {Year: 2010, Num: 269},
{Year: 2011, Num: 233}, {Year: 2012, Num: 196}, {Year: 2013, Num: 225},
{Year: 2014, Num: 228}, {Year: 2015, Num: 190}, {Year: 2016, Num: 138},
{Year: 2017, Num: 54}, {Year: 2018, Num: 26}
]
UK = [
{Year: 2009, Num: 40}, {Year: 2010, Num: 98}, {Year: 2011, Num: 148},
{Year: 2012, Num: 116}, {Year: 2013, Num: 161}, {Year: 2014, Num: 149},
{Year: 2015, Num: 123}, {Year: 2016, Num: 83}, {Year: 2017, Num: 84},
{Year: 2018, Num: 107}, {Year: 2019, Num: 107}
]
Germany = [
{Year: 2005, Num: 187}, {Year: 2006, Num: 151}, {Year: 2007, Num: 129},
{Year: 2008, Num: 103}, {Year: 2009, Num: 137}, {Year: 2010, Num: 85},
{Year: 2011, Num: 142}, {Year: 2012, Num: 132}, {Year: 2013, Num: 186},
{Year: 2014, Num: 219}, {Year: 2015, Num: 491}, {Year: 2016, Num: 330},
{Year: 2017, Num: 107}, {Year: 2018, Num: 129}, {Year: 2019, Num: 174},
{Year: 2020, Num: 151}, {Year: 2021, Num: 89}, {Year: 2022, Num: 143},
{Year: 2023, Num: 196}, {Year: 2024, Num: 170}
]
// Create a dropdown which dataset to display (Inputs.select) - Inputs.radio for radio buttons
// FIRST VERSION: viewof dataset = Inputs.radio(["IT (FARPO)", "UnitedKingdom (FRGB)", "DE (BT)"], {label: "Dataset"})
viewof datasets = Inputs.checkbox(
["IT (FARPO)", "UK (FRGB)", "DE (BT)"],
{label: "", value: ["IT (FARPO)", "UK (FRGB)", "DE (BT)"]}
)
// Choose the corresponding dataset based on the selection
// FIRST VERSION: selected_data = dataset === "IT (FARPO)" ? Italy : dataset === "UK (FRGB)" ? UK : Germany
// Combine the selected datasets into one array
selected_data = datasets.flatMap(dataset => {
if (dataset === "IT (FARPO)") {
return Italy.map(d => ({...d, dataset: "Italy"}));
} else if (dataset === "UK (FRGB)") {
return UK.map(d => ({...d, dataset: "UK"}));
} else if (dataset === "DE (BT)") {
return Germany.map(d => ({...d, dataset: "Germany"}));
}
return [];
});// plot as a bar plot
// FIRST VERSION: Plot.plot({
// x: {
// label: "", tickSize: 2, tickRotate: -45,
// tickFormat: d => d.toString() // Converts the year to a string to avoid number formatting
// },
// y: {
// grid: true
// },
// margin: 100,
// marks: [
// Plot.barY(selected_data, {x: "Year", y: "Num", fill: "darkred"})
// ],
// width: 1200,
// height: 600,
// style: {
// fontSize: 30,
// },
// })
// plot as a bar plot with dodged bars colored by dataset
Plot.plot({
x: {
label: "",
tickSize: 2,
tickRotate: -45,
tickFormat: d => d.toString()
},
y: {
grid: true
},
color: {
legend: true,
domain: ["Italy", "UK", "Germany"],
range: ["#FF6347", "#4682B4", "#32CD32"]
},
margin: 100,
marks: [
Plot.barY(selected_data, {
x: "Year",
y: "Num",
fill: "dataset",
groupby: "dataset",
x1: "dataset"
})
],
width: 1200,
height: 600,
style: {
fontSize: 28
}
})# A tibble: 3,451 × 14
Datum Land Ort Veranstalter Anmelder Zuordnung Motto Teiln. Country
<date> <chr> <chr> <lgl> <lgl> <chr> <chr> <dbl> <chr>
1 2005-01-15 Sachse… Magd… NA NA Neonazis… Bomb… 1000 Germany
2 2005-01-15 Bayern Nürn… NA NA Neonazis… Gege… 80 Germany
3 2005-01-17 Meckle… Stra… NA NA NPD/JN Gege… 8 Germany
4 2005-01-18 Nordrh… Reck… NA NA Neonazis… Stop… 70 Germany
5 2005-01-21 Baden-… Schw… NA NA Neonazis… Bürg… 30 Germany
6 2005-01-22 Nordrh… Moers NA NA Neonazis… Nein… 100 Germany
7 2005-01-23 Nordrh… Herne NA NA Neonazis… Gege… 30 Germany
8 2005-01-26 Nordrh… Hamm NA NA Neonazis… Kein… 160 Germany
9 2005-01-28 Nordrh… Hamm NA NA Neonazis… Gege… 110 Germany
10 2005-01-29 Schles… Kiel NA NA Neonazis… Gege… 450 Germany
# ℹ 3,441 more rows
# ℹ 5 more variables: lat <dbl>, long <dbl>, Jahr <date>, Latitude <dbl>,
# Longitude <dbl>
# A tibble: 236 × 2
month Num
<date> <int>
1 2005-01-01 13
2 2005-02-01 1
3 2005-03-01 13
4 2005-04-01 15
5 2005-05-01 20
6 2005-06-01 12
7 2005-07-01 13
8 2005-08-01 20
9 2005-09-01 23
10 2005-10-01 16
# ℹ 226 more rows
de_demos %>%
mutate(month=floor_date(Datum, "month")) %>%
group_by(month) %>% summarise(Num=n()) %>%
ggplot(aes(x=month, y=Num))+ geom_bar(stat="identity")+
scale_x_date("", labels=scales::date_format("%b %Y"), breaks="6 month",
limits=c(min(as.Date(de_demos$Datum)),max(as.Date(de_demos$Datum))),expand=c(0,0))+
theme_minimal()+ylab("")+
theme(text=element_text(size=38),
axis.text.x=element_text(angle=90, hjust=1, vjust=0.5))library(tmap)
library(tidyverse)
library(sf)
library(rnaturalearth)
library(gganimate)
library(gifski)
de_demos$Jahr <- format(
as.Date(de_demos$Jahr), format="%Y"
)
de_demos_grouped <- de_demos %>%
group_by(Ort, Jahr, lat, long) %>%
summarise(protests = n(),
.groups = "drop")
de_demos_grouped <- as.data.frame(
de_demos_grouped
)
de_demos_grouped$Latitude <- de_demos_grouped$lat
de_demos_grouped$Longitude <- de_demos_grouped$long
de_demos_grouped_sf <- de_demos_grouped %>%
drop_na(lat)
de_demos_grouped_sf <- de_demos_grouped_sf %>%
st_as_sf(
coords=c("long", "lat"),
crs=st_crs("EPSG:32632") # CRS for DE
)
DE = ne_states(returnclass="sf") |>
filter(admin=="Germany")
st_crs(de_demos_grouped_sf) <- st_crs(DE)
fr_prot_anim <- tm_shape(DE)+
tm_polygons(fill="gold",
col="darkolivegreen")+
tm_shape(de_demos_grouped_sf)+
tm_bubbles(shape=21,
size="protests",
col="red",
scale=8,
alpha=0.5,
border.col="black")+
tm_facets(pages="Jahr")+
tm_layout(panel.label.size=4,
panel.label.color='black',
panel.label.bg.color='grey',
panel.label.height=3,
legend.text.size=1.5)
tmap_animation(
fr_prot_anim,
filename = "fr_prot_anim.gif",
delay = 50,
width = 1200, height = 1200
)FARPO %>%
filter(Country_string=="Italy") %>%
mutate(month=floor_date(Date, "month")) %>%
group_by(month) %>% summarise(Num=n()) %>%
ggplot(aes(x=month, y=Num))+ geom_bar(stat="identity")+
scale_x_date("", labels=scales::date_format("%b %Y"), breaks="6 month",
limits=c(min(as.Date(FARPO$Date)),max(as.Date(FARPO$Date))),expand=c(0,0))+
theme_minimal()+ylab("")+
theme(text=element_text(size=38),
axis.text.x=element_text(angle=90, hjust=1, vjust=0.5))frgb %>%
mutate(month=floor_date(Date, "month")) %>%
group_by(month) %>% summarise(Num=n()) %>%
ggplot(aes(x=month, y=Num))+ geom_bar(stat="identity")+
scale_x_date("", labels=scales::date_format("%b %Y"), breaks="6 month",
limits=c(min(as.Date(frgb$Date)),max(as.Date(frgb$Date))),expand=c(0,0))+
theme_minimal()+ylab("")+
theme(text=element_text(size=38),
axis.text.x=element_text(angle=90, hjust=1, vjust=0.5))f_iss1 <- FARPO %>%
group_by(Issue1_string) %>%
summarise(Num=n()) %>%
as.data.frame() %>%
rename(Issue=Issue1_string)
f_iss2 <- FARPO %>%
group_by(Issue2_string) %>%
summarise(Num=n()) %>%
as.data.frame() %>%
rename(Issue=Issue2_string)
f_iss3 <- FARPO %>%
group_by(Issue3_string) %>%
summarise(Num=n()) %>%
as.data.frame() %>%
rename(Issue=Issue3_string)
merged_iss <- purrr::reduce(list(f_iss1, f_iss2, f_iss3),
function(x, y) merge(x, y, by="Issue", all=TRUE))
iss_final <- merged_iss %>%
group_by(Issue) %>%
summarise(Num=sum(coalesce(Num.x, 0), coalesce(Num.y, 0), coalesce(Num, 0))) %>%
slice(-1:-11) %>%
as.data.frame()
library(ggwordcloud)
set.seed(1)
ggplot(iss_final, aes(label=Issue, size=Num, color=Num)) +
geom_text_wordcloud() +
scale_size_area(max_size=10) +
theme_minimal()+
scale_color_gradient(low="blue", high="red")
prohibit_fr_demosCounts = aq.from(surveyResults)
.select("prohibit_fr_demos")
.groupby("prohibit_fr_demos")
.count()
.derive({ measure: d => "" })
// Calculate the maximum count from your dataset
prohibit_fr_demos_maxCountRE = Math.max(...prohibit_fr_demosCounts.objects().map(d => d.count));
plot_prohibit_fr_demos = Plot.plot({
marks: [
Plot.barY(prohibit_fr_demosCounts, {
x: "prohibit_fr_demos",
y: "count",
fill: "prohibit_fr_demos",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"Strongly disagree",
"Disagree",
"Neutral",
"Agree",
"Strongly agree"
],
range: [
"red",
"darkred",
"black",
"forestgreen",
"green"
]
},
marginBottom: 90,
x: { label: "", tickSize: 2, tickRotate: 0,
domain: ["Strongly\ndisagree", "Disagree", "Neutral", "Agree", "Strongly\nagree"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(prohibit_fr_demosCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, prohibit_fr_demos_maxCountRE]
},
facet: { data: prohibit_fr_demosCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1350,
height: 500,
fontSize: 20,
}
});respond_countermobCounts = aq.from(surveyResults)
.select("respond_countermob")
.groupby("respond_countermob")
.count()
.derive({ measure: d => "" })
// Calculate the maximum count from your dataset
respond_countermob_maxCountRE = Math.max(...respond_countermobCounts.objects().map(d => d.count));
plot_respond_countermob = Plot.plot({
marks: [
Plot.barY(respond_countermobCounts, {
x: "respond_countermob",
y: "count",
fill: "respond_countermob",
stroke: "black",
strokeWidth: 1
}),
Plot.ruleY([respondentCount], { stroke: "#ffffff99" })
],
color: {
domain: [
"ban both",
"ban counter-mobilisation",
"ban far-right demonstration",
"keep protests separated",
"nothing",
"other"
],
range: [
"darkred",
"darkorange",
"goldenrod",
"forestgreen",
"blue",
"indigo"
]
},
marginBottom: 220,
x: { label: "", tickSize: 2, tickRotate: -35, padding: 0.3,
domain: ["ban both", "ban counter-mobilisation", "ban far-right demonstration", "keep protests separated", "nothing", "other"]
},
y: {
label: "",
tickSize: 10,
tickFormat: d => d,
tickValues: Array.from(
new Set(respond_countermobCounts.objects().map(d => d.count))
).sort((a, b) => a - b),
domain: [0, respond_countermob_maxCountRE]
},
facet: { data: respond_countermobCounts, x: "measure", label: "" },
marginLeft: 140,
style: {
width: 1600,
height: 500,
fontSize: 30,
},
});Anonymous feedback here: https://forms.gle/pisUmtmWdE13zMD58
Alternatively, send me an email: m.zeller@lmu.de
Social movement lens on the far right